package com.sky.aspect;

import com.sky.anno.TableInject;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
public class TableInjectAspect {
    @Pointcut("execution(* com.sky.mapper..*(..)) && @annotation(com.sky.anno.TableInject)")
    public void pt(){}
    @Before("pt()")
    public void before(JoinPoint jp){
        //获取方法签名
        MethodSignature signature = (MethodSignature) jp.getSignature();
        //获取方法
        Method method = signature.getMethod();
        //获取方法上的注解 => 获取注解里的value
        OperationType operationType = method.getAnnotation(TableInject.class).value();
        Object target = jp.getArgs()[0];
        if (target == null || jp.getArgs().length == 0 || jp.getArgs().length > 1){
            return;
        }
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();
        try {
            Method createTimeMethod = target.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method updateTimeMethod = target.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method createUserMethod = target.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method updateUserMethod = target.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            switch (operationType){
                case INSERT:
                    createTimeMethod.invoke(target,now);
                    updateTimeMethod.invoke(target,now);
                    createUserMethod.invoke(target,currentId);
                    updateUserMethod.invoke(target,currentId);
                    break;
                case UPDATE:
                    updateTimeMethod.invoke(target,now);
                    updateUserMethod.invoke(target,currentId);
                    break;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}
